package secondriver.heathfood.util;

import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import secondriver.heathfood.client.Constants;

import java.io.*;

import static android.os.Environment.*;


/**
 * Author : secondriver
 */
public class SimpleDiskCache {

    private static final LogUtil logUtil = LogUtil.getLogger(SimpleDiskCache.class.getName());

    private int mode = Context.MODE_PRIVATE;
    private final String name;
    private Context context;
    private SharedPreferences preferences;

    /**
     * 缓存对象
     *
     * @param context 上下文环境
     * @param name    缓存名称，作为缓存文件或目录的名称
     */
    public SimpleDiskCache(Context context, String name) {
        this.name = name;
        this.context = context;
        this.preferences = context.getSharedPreferences(name, mode);
        logUtil.info("Create simpleDiskCache name is %s .", name);
    }

    public boolean putToPreference(String key, String value) {
        SharedPreferences.Editor editor = preferences.edit();
        editor.putString(key, value);
        return editor.commit();
    }

    public boolean isExistInPreference(String key) {
        return preferences.contains(key);
    }

    public String getFromPreference(String key) {
        String defaultValue = "";
        if (isExistInPreference(key)) {
            return preferences.getString(key, defaultValue);
        } else {
            putToPreference(key, defaultValue);
            return defaultValue;
        }
    }

    public InputStream getCacheInputStreamFromDisk(String cacheFileName) {
        File cacheFile = new File(getCacheDir(context, name), cacheFileName);
        if (!cacheFile.exists()) {
            return null;
        }
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(cacheFile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return inputStream;
    }


    public OutputStream getCacheOutputStreamToDisk(String cacheFileName) {
        File cacheFile = new File(getCacheDir(context, name), cacheFileName);
        if (!cacheFile.exists()) {
            try {
                if (!cacheFile.createNewFile()) {
                    return null;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        OutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(cacheFile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return outputStream;
    }

    public Bitmap getBitmapFromCache(String cacheFileName) {
        InputStream inputStream = null;
        if (cacheFileName != null) {
            inputStream = getCacheInputStreamFromDisk(cacheFileName);
        }
        if (null != inputStream) {
            try {
                return BitmapFactory.decodeStream(inputStream);
            } finally {
                if (null != inputStream) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return null;
    }

    public void putBitmapToCache(Bitmap bitmap, String cacheFileName, String imageUrl) {
        OutputStream outputStream = null;
        if (cacheFileName != null) {
            outputStream = getCacheOutputStreamToDisk(cacheFileName);
        }
        try {
            if (null != outputStream && imageUrl != null) {
                Bitmap.CompressFormat format = Bitmap.CompressFormat.PNG;
                if (imageUrl.endsWith("jpg")) {
                    format = Bitmap.CompressFormat.JPEG;
                }
                if (imageUrl.endsWith("png")) {
                    format = Bitmap.CompressFormat.PNG;
                }
                bitmap.compress(format, 100, outputStream);
            }
        } finally {
            if (null != outputStream) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    private static File getCacheDir(Context context, String uniqueName) {
        File cacheDir;
        if (getExternalStorageState().equals(MEDIA_MOUNTED) || !Environment.isExternalStorageRemovable()) {
            String dir = getExternalStorageDirectory() + Constants.ANDROID_DATA_EXTERNAL + context.getPackageName() + Constants.ANDROID_DATA_FILES_EXTERNAL + uniqueName;
            cacheDir = new File(dir);
        } else {
            cacheDir = new File(context.getCacheDir(), uniqueName);
        }
        if (!cacheDir.exists()) {
            if (cacheDir.mkdirs()) {
            }
        }
        logUtil.info("Cache file directory is %s.", cacheDir.getAbsolutePath());
        return cacheDir;
    }

    public static String genCacheFileName(String value) {
        if (null == value || value.equals("")) {
            return null;
        }
        return value.replaceAll("/", "_");
    }

    public static String getCacheSize(Context context) {
        File cacheFileDir = getCacheDir(context, Constants.FOOD_DETAIL_CACHE_NAME);
        long totalFileSize = 0;
        if (cacheFileDir.isDirectory()) {
            for (File f : cacheFileDir.listFiles()) {
                if (f.isFile()) {
                    totalFileSize += f.length();
                }
            }
        } else {
            totalFileSize += cacheFileDir.length();
        }
        return humanReadableFileSize(totalFileSize);
    }


    public static String humanReadableFileSize(long size) {
        float[] dividends = {1F, 1024F, 1048576F, 1073741824F};
        String[] units = {"B", "KB", "MB", "GB"};//dividends[i] <-> units[i]
        int index = 0;
        for (int i = dividends.length - 1; i >= 0; i--) {
            if (size >= dividends[i]) {
                index = i;
                break;
            }
        }
        return String.format("%.2f%s", size / dividends[index], units[index]);
    }

    public static void clearCache(Context context) {
        File cacheFileDir = getCacheDir(context, Constants.FOOD_DETAIL_CACHE_NAME);
        delete(cacheFileDir);
    }

    private static void delete(File fileDir) {
        if (fileDir.isDirectory()) {
            for (File f : fileDir.listFiles()) {
                if (f.isFile()) {
                    f.delete();
                } else {
                    delete(f);
                }
            }
        }
    }
}